#import "Warp1.h"
#import "Thinker.h"
#define PI (3.141592653589)

@implementation Warp1


- init
{
    	[super init];

    return self;
    
}
// Every module should have a first state
//since class info only gets loaded once
- setFirstState
{
int ii = 0;
	starCounter = 0;
	if(soundEnabled){
		[pwrUpSnd play];
	}
    firstState = YES;
	currentCycle = 1;
	[self setCenter]; 

	[starsObject setStarsStopped];  //put out all stars at once
	[starsObject startStars];
	starsStopped = NO;
	starsStopping = NO;
	totalStopped = 0; 
	for(ii = 0;ii < MAXLINES;ii++){
		lines[ii].toggle = 1;
		lines[ii].stopped = 0;
		[self newLine:ii];
		lines[ii].delay = randBetween(0.0,5.0);  //override set value
	}
	
	return self;
}
- (BOOL)doUntilDone
{
int ii;

BOOL done;

	done = NO;
	
	
	if(!starsStopped || totalStopped < MAXLINES){	
		for(ii = 0;ii < MAXLINES;ii++){
	 	 	if(lines[ii].delay < 0){
		 		if(!lines[ii].toggle){ //erase line

					[self eraseLine:ii];	 
					if((lines[ii].dist1 > ceil(radius)) && !lines[ii].stopped){

						//add new one
						if(!starsStopping){
							starCounter++;
							lines[ii].toggle = 1;
							[self newLine:ii];
							//bring new one on screen
							[self drawLine:ii];
						}
						else{
							lines[ii].stopped = 1;
							totalStopped++;
						}
					}
					else {
						if(!lines[ii].stopped)
							[self newDist:ii];
					} 
			
				}
				else{ //draw line
					[self drawLine:ii];
					[self newDist:ii]; 
			
					if((lines[ii].dist1) > ceil(radius)){
						lines[ii].dist1 = lines[ii].oldDist1 =
					 	lines[ii].startDist;
						lines[ii].length = lines[ii].oldLength = 1;
						lines[ii].toggle = 0;
					}
				
				} 
			}
			else
				lines[ii].delay--;
		}
		if(!starsStopping){
			if(starCounter > MAXLINES){ 
				currentCycle++;
				starCounter = 0;
			}
			if(currentCycle > cycles){
				if(soundEnabled)
					[pwrDownSnd play];
					[starsObject stopStars];  
					for(ii = 0;ii < MAXLINES;ii++){
					lines[ii].delay = 0;
				}
				totalStopped = 0;
				starsStopping = YES;
			}
		}
	}	
	else{ //stars are stopping
		if(starsStopped){
			PSsetlinewidth(0.0);  //reset
			done = YES;
		}
	}
	return done;
}

//takes theta and distance and stuffs it into point x & y
- convertToXY:(float)dist :(NXPoint *)point :(float)theta
{
	point->x = floor(centerOfScreen.x + (dist * cos(theta)));
	point->y = floor(centerOfScreen.y  + (dist * sin(theta)));
	return self;
}

//calculates new length and updates everything
- newDist:(int)index
{
	lines[index].oldDist1 = lines[index].dist1;
	lines[index].oldLength = lines[index].length;
	if(lines[index].toggle)
		lines[index].dist1 = lines[index].dist1 + lines[index].length;
	else //erasing
		lines[index].dist1 = lines[index].dist1 + lines[index].length;
	lines[index].length = lines[index].length
	 + objectSpeed;
	 
	if(lines[index].dist1 + lines[index].length > radius)
		lines[index].length = radius - lines[index].dist1 + 5;
	lines[index].r = randBetween(0,1); //random colors
	lines[index].g = randBetween(0,1);
	lines[index].b = randBetween(0,1);
	return self;
}
//generate new line values
- newLine:(int)index
{
	lines[index].dist1 = lines[index].oldDist1 = randBetween(0,radius);
	lines[index].startDist = lines[index].dist1 - 2;
	if(lines[index].startDist < 0.0)
		lines[index].startDist = 0.0;
	lines[index].length = lines[index].oldLength = 1.0;
	lines[index].delay = floor(randBetween(30,startInterval));
	lines[index].theta = randBetween(0,(2*PI));
	lines[index].r = 1.0;  //start out as white
	lines[index].g = 1.0;
	lines[index].b = 1.0;
	return self;
}

//between 1 - 2
- setStarSpeed:sender
{
	starSpeed = ([sender floatValue]);
	return self; 	
}

// between 0-500
- setStartInterval: (Slider *)sender;
{

	startInterval = [sender intValue];
	return self;

}
//between 1 - 200
- setObjectSpeed: (Slider *)sender
{
	objectSpeed =[sender floatValue];
	return self;
}

- setBoundsRect:(NXRect *)r
{
    bounds.origin.x = r->origin.x;
    bounds.origin.y  = r->origin.y;
    bounds.size.width = r->size.width;
    bounds.size.height = r->size.height;
    return self;
}

- setCenter
{
float x,y;

    centerOfScreen.x = (bounds.size.width / 2) + bounds.origin.x;
 	centerOfScreen.y = bounds.size.height / 2 + bounds.origin.y;
	x = bounds.size.width;
	y = bounds.size.height;
	radius = (sqrt(x*x + y*y))/2;
    return self;
}
- drawLine:(int)index
{
NXPoint p1,p2;
	PSsetlinewidth(0.0);

	[self convertToXY:lines[index].dist1 :&p1 :lines[index].theta];
	[self convertToXY:(lines[index].dist1+lines[index].length) 
	 :&p2 :lines[index].theta];
	PSDrawLine(p1.x,p1.y,p2.x,p2.y,lines[index].r,
	 lines[index].g,lines[index].b); 
	return self;
}
- eraseLine:(int)index
{
NXPoint p1,p2;

	PSsetlinewidth(4.0);

	[self convertToXY:lines[index].dist1 :&p1 :lines[index].theta];
	[self convertToXY:(lines[index].dist1+lines[index].length) 
	 :&p2 :lines[index].theta];
	PSDrawLine(p1.x,p1.y,p2.x,p2.y,0.0,0.0,0.0); 
	return self;
}

- setPwrDownSnd:(Sound *)theSound
{
	pwrDownSnd = theSound;
	return self;
}
- setPwrUpSnd:(Sound *)theSound;
{
	pwrUpSnd = theSound;
	return self;
}

- starsStopped
{
	starsStopped = YES;
	return self;
}
- setStarsOutlet:(id)starsOutlet;
{
	starsObject = starsOutlet;
	return self;
}
- (int)setCycleValue:(int)value;
{
int mutiplier;
	// since this one cycles very fast, make it 9 times the slider value
	// could be zero
	
	mutiplier = 9;
	if(!value)
		value = 1;
	else
		value *= mutiplier;
	cycles = value;
	currentCycle = 1;
	return mutiplier;
}

- windowSizeChanged
{
int ii;
	[self setCenter];
	starsStopped = NO;
	starsStopping = NO;
	totalStopped = 0; 
	for(ii = 0;ii < MAXLINES;ii++){
		lines[ii].toggle = 1;
		lines[ii].stopped = 0;
		[self newLine:ii];
		lines[ii].delay = randBetween(0.0,5.0);  //override set value
	}
	return self;
}
- freeResources
{//not used in this module
	return self;
}

- setSoundEnabled:(BOOL)enabled
{
	soundEnabled = enabled;
	return self;
}
@end
